/*
 * CProcess - process wrapper implmn
 * Kannan Ramanathan
 */
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.IO;

namespace uciPlug
{
	/// <summary>
	/// Summary description for CProcess.
	/// </summary>
	public class CProcess
	{
		private Process process;
		private string processName;
		private StreamReader processOutput;
		private StreamWriter processInput;
		
		/// <summary>
		/// Initializes a new instance of the <see cref="CProcess"/> class.
		/// </summary>
		public CProcess()
		{
			// Empty constructor
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="CProcess"/> class.
		/// </summary>
		/// <param name="exeName">Name of the exe.</param>
		public CProcess(string exeName)		
		{
			this.processName = exeName;
		}
		/// <summary>
		/// Inits the process.
		/// </summary>
		/// <param name="processName">Name of the process.</param>
		/// <returns>Sucess or Failure</returns>
		public bool initProcess(string processName)
		{
			Debug.Assert(processName.Length != 0, @"setupPump(): NULL process name passed");
			Debug.Assert(File.Exists(processName) != false, @"setupPump(): Process "+processName+" not found");
			
			this.processName = processName;		
			return initProcess();
		}

		/// <summary>
		/// Inits the process - Core function.
		/// </summary>
		/// <returns>Sucess or failure</returns>
		public bool initProcess()
		{
            bool processStarted = false;
			Debug.WriteLineIf(processName == "", "setupPump::processname cannot be null here");
			try 
			{
				/// Create a new process & setup the startup info struct
				process = new Process();
				
				process.StartInfo.FileName = processName;
				process.StartInfo.RedirectStandardInput = true;
				process.StartInfo.RedirectStandardOutput = true;				
				process.StartInfo.UseShellExecute = false;
				process.StartInfo.CreateNoWindow = true;

				/// Load the process now
				processStarted = process.Start();				

				/// Get the stream mappings
				processOutput = process.StandardOutput;			
				processInput = process.StandardInput;
                processInput.AutoFlush = true;

				return processStarted;
			}
			catch (Exception e)
			{
				string error = e.Message + "\n"+e.ToString();
				Debug.WriteLine(error);
                return processStarted;
			}           
		}
        
		/// <summary>
		/// Reads the process output line.
		/// </summary>
		/// <returns>one line read from process's output</returns>
		public string readProcessOutputLine()
		{
            Debug.Assert(process != null, "readProcessOutputLine: process not init yet");
		    
            string s = processOutput.ReadLine();            
            return s;
		}

        /// <summary>
        /// Reads the process output to end.
        /// </summary>
        /// <returns>Process output till end of stream</returns>
        public string readProcessOutputToEnd()
        {            
            string s = processOutput.ReadToEnd();
            return s;
        }
		/// <summary>
		/// Writes the process input line.
		/// </summary>
		/// <param name="inputLine">The input line.</param>
		public void writeProcessInputLine(string inputLine)
		{
            Debug.Assert(process != null, "writeProcessInputLine: process not init yet");			
            processInput.WriteLine(inputLine);
            processInput.Flush();
		}

		/// <summary>
		/// Terminates this instance.
		/// </summary>
		public void terminate()
		{
			Debug.Assert(process != null, "Terminate:: process not init yet");
			
			writeProcessInputLine("quit");
			if (!process.HasExited)
			{
                process.Kill();                
			}
            process.Close();
		}
	}
}